package com.zyy.java8.samples.stream;

import java.util.Arrays;
import java.util.List;

/**
 * @author zhangyiying
 * @ClassName: Streams11
 * @Description: reduce 规约操作
 * reduce操作： reduce:(T identity,BinaryOperator)/reduce(BinaryOperator)-可以将流中元素反复结合起来，得到一个值
 * @date 2021/12/30 16:11
 */
public class Streams11 {

    static class Person {
        String name;
        int age;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public String toString() {
            return name;
        }
    }

    public static void main(String[] args) {
        List<Person> persons =
                Arrays.asList(
                        new Person("Max", 18),
                        new Person("Peter", 23),
                        new Person("Pamela", 23),
                        new Person("David", 12));

//        test1(persons);
//        test2(persons);
//        test3(persons);
//        test4(persons);
//        test5(persons);
        test6(persons);
    }

    private static void test1(List<Person> persons) {
        persons
                .stream()
                .reduce((p1, p2) -> p1.age > p2.age ? p1 : p2)
                .ifPresent(System.out::println);
        //Pamela

    }

    private static void test2(List<Person> persons) {
        Person resultPerson = persons
                .stream()
                .reduce(new Person("", 0), (p1, p2) -> {
                    p1.name += p2.name;
                    p1.age += p2.age;
                    return p1;
                });

        //name: MaxPeterPamelaDavid ,age : 76
        System.out.printf("name: %s ,age : %s \n", resultPerson.name, resultPerson.age);
    }

    private static void test3(List<Person> persons) {
        Integer ageSum = persons
                .stream()
                .reduce(0,
                        (sum, p) -> sum += p.age,
                        (sum1, sum2) -> sum1 + sum2);

        //76
        System.out.println(ageSum);
    }

    private static void test4(List<Person> persons) {

        Integer ageSum = persons
                .stream()
                .reduce(0,
                        (sum, p) -> {
                            System.out.format("accumulator: sum = %s ,person = %s \n", sum, p);
                            return sum += p.age;
                        },
                        (sum1, sum2) -> {
                            System.out.format("combiner : sum1 = %s, sum2 = %s \n", sum1, sum2);
                            return sum1 + sum2;
                        });

        //accumulator: sum = 0 ,person = Max
        //accumulator: sum = 18 ,person = Peter
        //accumulator: sum = 41 ,person = Pamela
        //accumulator: sum = 64 ,person = David
        //76
        System.out.println(ageSum);
    }

    /**
     * 当进行并行流操作的时候 BinaryOperator的作用就会显现出来
     * @param persons
     */
    private static void test5(List<Person> persons) {
        Integer ageSum = persons
                .parallelStream()
                .reduce(0,
                        (sum, p) -> {
                            System.out.format("accumulator: sum = %s ,person = %s \n", sum, p);
                            return sum += p.age;
                        },
                        (sum1, sum2) -> {
                            System.out.format("combiner : sum1 = %s, sum2 = %s \n", sum1, sum2);
                            return sum1 + sum2;
                        });

        //accumulator: sum = 0 ,person = Max
        //accumulator: sum = 0 ,person = David
        //accumulator: sum = 0 ,person = Pamela
        //accumulator: sum = 0 ,person = Peter
        //combiner : sum1 = 18, sum2 = 23
        //combiner : sum1 = 23, sum2 = 12
        //combiner : sum1 = 41, sum2 = 35
        //76
        System.out.println(ageSum);
    }


    private static void test6(List<Person> persons){
        Integer ageSum = persons
                .parallelStream()
                .reduce(0,
                        (sum, p) -> {
                            System.out.format("accumulator: sum=%s; person=%s; thread=%s\n",
                                    sum, p, Thread.currentThread().getName());
                            return sum += p.age;
                        },
                        (sum1, sum2) -> {
                            System.out.format("combiner: sum1=%s; sum2=%s; thread=%s\n",
                                    sum1, sum2, Thread.currentThread().getName());
                            return sum1 + sum2;
                        });

        //某一种运行结果
        //accumulator: sum=0; person=Pamela; thread=main
        //accumulator: sum=0; person=Max; thread=ForkJoinPool.commonPool-worker-3
        //accumulator: sum=0; person=Peter; thread=ForkJoinPool.commonPool-worker-1
        //accumulator: sum=0; person=David; thread=ForkJoinPool.commonPool-worker-2
        //combiner: sum1=23; sum2=12; thread=ForkJoinPool.commonPool-worker-2
        //combiner: sum1=18; sum2=23; thread=ForkJoinPool.commonPool-worker-1
        //combiner: sum1=41; sum2=35; thread=ForkJoinPool.commonPool-worker-1
        //76
        System.out.println(ageSum);

    }

}
